{
 "cells": [
  {
   "cell_type": "markdown",
   "id": "54bd0c25",
   "metadata": {},
   "source": [
    "#### 第3章　神经网络\n",
    "- 展示mnist数据集\n",
    "- "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 15,
   "id": "5f07cbfb",
   "metadata": {},
   "outputs": [],
   "source": [
    "# %% [markdown]\n",
    "# # MNIST 数据集加载与可视化\n",
    "# \n",
    "# 本笔记本包含完整的 MNIST 数据集加载和显示功能，无需外部依赖（除标准库外）。\n",
    "\n",
    "# %%\n",
    "import numpy as np\n",
    "import os\n",
    "import gzip\n",
    "import struct\n",
    "from PIL import Image\n",
    "import matplotlib.pyplot as plt\n",
    "from urllib.request import urlretrieve\n",
    "import shutil\n",
    "\n",
    "# %% [markdown]\n",
    "# ## 1. MNIST 工具函数\n",
    "\n",
    "# %%\n",
    "def _load_mnist_images(filename):\n",
    "    \"\"\"加载MNIST图像文件\"\"\"\n",
    "    with gzip.open(filename, 'rb') as f:\n",
    "        magic, num, rows, cols = struct.unpack(\">IIII\", f.read(16))\n",
    "        images = np.frombuffer(f.read(), dtype=np.uint8)\n",
    "        images = images.reshape(num, rows, cols)\n",
    "    return images\n",
    "\n",
    "def _load_mnist_labels(filename):\n",
    "    \"\"\"加载MNIST标签文件\"\"\"\n",
    "    with gzip.open(filename, 'rb') as f:\n",
    "        magic, num = struct.unpack(\">II\", f.read(8))\n",
    "        labels = np.frombuffer(f.read(), dtype=np.uint8)\n",
    "    return labels\n",
    "\n",
    "def download_mnist(mnist_dir):\n",
    "    \"\"\"下载MNIST数据集(如果不存在)\"\"\"\n",
    "    base_url = \"http://yann.lecun.com/exdb/mnist/\"\n",
    "    files = [\n",
    "        'train-images-idx3-ubyte.gz',\n",
    "        'train-labels-idx1-ubyte.gz',\n",
    "        't10k-images-idx3-ubyte.gz',\n",
    "        't10k-labels-idx1-ubyte.gz'\n",
    "    ]\n",
    "    \n",
    "    os.makedirs(mnist_dir, exist_ok=True)\n",
    "    \n",
    "    for file in files:\n",
    "        if not os.path.exists(os.path.join(mnist_dir, file)):\n",
    "            print(f\"Downloading {file}...\")\n",
    "            urlretrieve(base_url + file, os.path.join(mnist_dir, file))\n",
    "        else:\n",
    "            print(f\"{file} already exists, skipping download.\")\n",
    "\n",
    "# %% [markdown]\n",
    "# ## 2. 主加载函数\n",
    "\n",
    "# %%\n",
    "def load_mnist(mnist_dir, flatten=True, normalize=True, one_hot_label=False):\n",
    "    \"\"\"\n",
    "    加载MNIST数据集\n",
    "    \n",
    "    参数:\n",
    "        mnist_dir: MNIST文件目录\n",
    "        flatten: 是否将图像展平为一维数组 (默认True)\n",
    "        normalize: 是否将像素值归一化到0.0~1.0 (默认True)\n",
    "        one_hot_label: 是否使用one-hot编码标签 (默认False)\n",
    "    \n",
    "    返回:\n",
    "        (训练图像, 训练标签), (测试图像, 测试标签)\n",
    "    \"\"\"\n",
    "    # 确保数据集存在\n",
    "    download_mnist(mnist_dir)\n",
    "    \n",
    "    # 加载训练数据\n",
    "    train_images = _load_mnist_images(os.path.join(mnist_dir, 'train-images-idx3-ubyte.gz'))\n",
    "    train_labels = _load_mnist_labels(os.path.join(mnist_dir, 'train-labels-idx1-ubyte.gz'))\n",
    "    \n",
    "    # 加载测试数据\n",
    "    test_images = _load_mnist_images(os.path.join(mnist_dir, 't10k-images-idx3-ubyte.gz'))\n",
    "    test_labels = _load_mnist_labels(os.path.join(mnist_dir, 't10k-labels-idx1-ubyte.gz'))\n",
    "    \n",
    "    # 归一化处理\n",
    "    if normalize:\n",
    "        train_images = train_images.astype(np.float32) / 255.0\n",
    "        test_images = test_images.astype(np.float32) / 255.0\n",
    "    \n",
    "    # 展平处理\n",
    "    if flatten:\n",
    "        train_images = train_images.reshape(train_images.shape[0], -1)\n",
    "        test_images = test_images.reshape(test_images.shape[0], -1)\n",
    "    \n",
    "    # One-hot编码处理\n",
    "    if one_hot_label:\n",
    "        train_labels = np.eye(10)[train_labels]\n",
    "        test_labels = np.eye(10)[test_labels]\n",
    "    \n",
    "    return (train_images, train_labels), (test_images, test_labels)\n",
    "\n",
    "# %% [markdown]\n",
    "# ## 3. 可视化工具\n",
    "\n",
    "# %%\n",
    "def img_show(img, reshape=True):\n",
    "    \"\"\"\n",
    "    显示MNIST图像\n",
    "    \n",
    "    参数:\n",
    "        img: 要显示的图像数组\n",
    "        reshape: 是否需要reshape为28x28 (默认True)\n",
    "    \"\"\"\n",
    "    if reshape and img.ndim == 1:\n",
    "        img = img.reshape(28, 28)\n",
    "    \n",
    "    if img.dtype == np.float32:\n",
    "        img = (img * 255).astype(np.uint8)\n",
    "    else:\n",
    "        img = img.astype(np.uint8)\n",
    "    \n",
    "    pil_img = Image.fromarray(img)\n",
    "    plt.imshow(pil_img, cmap='gray')\n",
    "    plt.axis('off')\n",
    "    plt.show()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 16,
   "id": "20795165",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "train-images-idx3-ubyte.gz already exists, skipping download.\n",
      "train-labels-idx1-ubyte.gz already exists, skipping download.\n",
      "t10k-images-idx3-ubyte.gz already exists, skipping download.\n",
      "t10k-labels-idx1-ubyte.gz already exists, skipping download.\n",
      "训练图像形状: (60000, 28, 28)\n",
      "对应标签: 5\n"
     ]
    },
    {
     "data": {
      "image/png": "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",
      "text/plain": [
       "<Figure size 640x480 with 1 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "data": {
      "image/png": "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AACSpxwDAACQvFq/rTqmPJveQgjho48+KvrsZZddFs1/85vfRPNCm3KhqrRv3z6TXXfdddGzhTbZrlq1KpqvWLEikxXaaLhhw4Zo/t///d9FZVWtUaNG0fw73/lOJrvggguqepxknHLKKdG80O8HxSm07btt27ZFX2PZsmWVNQ4UpUWLFtH861//eiYr9H5q7dq10fyHP/zhTs9FekaMGJHJbrzxxujZ2Cd3hBDC/fffH81jn8hR3q4S8/3vf7/C1wghhKFDh2ayQp8KUht4cgwAAEDylGMAAACSpxwDAACQPOUYAACA5CnHAAAAJC/JbdXldeutt0bzo48+OpP16tUrerZPnz7R/Nlnn93pueCzNGjQIJrfddddmazQhuD169dH80GDBkXzOXPmZLLatmX4gAMOyHuEWu2QQw4p1/k333yziiapXWL3fQjxLdYLFiyIni305wFUVJs2baL5xIkTK3zt++67L5pPnTq1wtem9rn55pujeWwz9datW6Nnn3nmmWh+/fXXR/NNmzYVOV0IDRs2jOZ9+/bNZIXer5SUlETzQhvcJ0+eXOR0tYMnxwAAACRPOQYAACB5yjEAAADJU44BAABInoVcRdi4cWM0v+yyyzLZa6+9Fj37s5/9LJrHFkLElhqFEMJPf/rTaF5WVhbNSduRRx4ZzQst34o544wzovlLL720UzNBZZs9e3beI1S5pk2bZrKTTjopenbgwIHRPLaspZARI0ZE87Vr1xZ9DSiPQl/PnTp1KvoaL7zwQjQfNWrUTs1E7bbnnntG8yuvvDKax95rF1q8deaZZ+7sWJ9q165dNB83blw0jy0JLmTChAnR/Ec/+lHR16jNPDkGAAAgecoxAAAAyVOOAQAASJ5yDAAAQPKUYwAAAJJnW3UFLFq0KJMNHjw4enbs2LHR/MILLywqCyGEJk2aRPNHH300mq9YsSKak4Z77rknmpeUlGSyQtunU9hKXadO/GeEpaWl1TwJO6N58+ZVct3OnTtH89j9E0IIffr0ieaf//znM1n9+vWjZy+44IJoHvsa3bRpU/TsrFmzovmWLVui+W67Zd8G/PnPf46ehcoQ2+R7xx13lOsar7zySia76KKLomc/+uijcl2bNBT6c7hFixZFX2Po0KHRfJ999onmF198cTTv169fJuvYsWP07O677x7NY9u0C32azWOPPRbNC306T2o8OQYAACB5yjEAAADJU44BAABInnIMAABA8pRjAAAAkmdbdSWbNGlSNF+4cGE0j20UPv7446Nnb7vttmh+4IEHRvORI0dmsmXLlkXPsus67bTTonmXLl2ieWx74ZQpUypzpF1Koa3UhbY8vv7661U4DYW2MBf6/XjwwQcz2Y033ljhOTp16hTNC22r/uSTT6L5xx9/nMnmzZsXPfuLX/wims+ZMyeTFdok//7770fzpUuXRvNGjRplsvnz50fPQnm0adMmmk+cOLHC1/7b3/6WyQp97UPM1q1bo/nKlSujecuWLTPZ3//+9+jZQt+vymP58uXRfN26ddG8devWmWzVqlXRs08++eTOD5YAT44BAABInnIMAABA8pRjAAAAkqccAwAAkDwLuarJ3Llzo/m5556byU4//fTo2bFjx0bzK664IpoffPDBmeyEE04oNCK7qNhCnRBCqF+/fjT/4IMPMtlvfvObSp0pbw0aNIjmt956a9HXePHFF6P5DTfcsDMjUaQrr7wymi9ZsiSad+/evUrmeOedd6L5E088Ec3feuutaD5z5szKGqkol19+eTSPLZMJIb7YCCrD9ddfH80LLUEsjzvuuKPC1yBta9eujeZnnnlmNH/qqacyWfPmzaNnFy1aFM0nT54czR955JFM9uGHH0bPjh8/PprHFnIVOstn8+QYAACA5CnHAAAAJE85BgAAIHnKMQAAAMlTjgEAAEiebdU5i23L+9WvfhU9+/DDD0fz3XaL/zb27Nkzk/Xu3Tt6dtq0adGc2mfLli2ZbMWKFTlMUnGFtlIPGzYsml933XWZbOnSpdGzd999dzTfsGFDkdNRme688868R9glHH/88eU6P3HixCqahFR06dIlmvft27fC1y603fevf/1rha8NMbNmzYrmhTb+V5XYe/gQQujVq1c0j22B92kEO8eTYwAAAJKnHAMAAJA85RgAAIDkKccAAAAkTzkGAAAgebZVV5NOnTpF83POOSeTde3aNXq20FbqQubNm5fJpk+fXq5rUPtMmTIl7xHKrdA21Nj26RBCGDBgQDSPbT49++yzd3ou2NVNmjQp7xHYxT377LPRfK+99ir6GjNnzozmgwcP3pmRYJfXqFGjaB7bSh1CCGVlZZls/PjxlTpTKjw5BgAAIHnKMQAAAMlTjgEAAEiecgwAAEDylGMAAACS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gAMqfO2uXbtmskJL55YsWVLh14OYBx54IJo/8cQT5brOtm3bMtl77723MyMVpWnTptF87ty50Xy//fYr+tqF/t3nzJlT9DWgPMrKyqJ5w4YNq3kSqDpjxozJZAcffHD07OGHHx7NX3nllUqd6V/deOONmWzvvfeOnr3sssui+RtvvFGpM1UlT44BAABInnIMAABA8pRjAAAAkqccAwAAkDzlGAAAgOQlua26f//+lXKdxYsXZ7LZs2dHz15//fXRvNBm6pjDDjus6LNQlZYvXx7NH3nkkUx26623luvasfNr166Nnh09enS5rg3F+uSTT6J5ef7MzsOJJ54Yzffaa68KX3vp0qXRfMuWLRW+NpTHMccck8lmzpyZwyRQcR9//HEmy2NTe5cuXaL5gQcemMlKS0ujZ2vDJnlPjgEAAEiecgwAAEDylGMAAACSpxwDAACQPOUYAACA5CW5rfqyyy6L5pdffnk0f/bZZ6P522+/nck++OCDnR/s39h3332r7NpQGUaMGJHJyrutGvj3zjvvvGhe6Ptbo0aNKvyaN998c4WvAbFN8B999FH0bLNmzaL5QQcdVKkzQXWIvUcKIYQjjjgik7311lvRs2+88UaF52jSpEk0L/TJOo0bN85khbbDT5gwYecHqyE8OQYAACB5yjEAAADJU44BAABInnIMAABA8pRjAAAAkpfkturly5dH85q+Vbdbt255jwDlVqdO/GdwpaWl1TwJ1GwXXHBBNP/e976Xydq1axc9W69evQrP8frrr0fzbdu2VfjasHbt2kz28ssvR8+edtppVTwNVL79998/mhf6NIHYBverrroqenblypU7P9j/ueeee6J5//79o3msN33pS1+q8Bw1lSfHAAAAJE85BgAAIHnKMQAAAMlTjgEAAEhekgu5qtLQoUOjeZMmTSp87SOOOKJc51999dVMNmPGjArPAeVRaPFWWVlZNU8CxWvTpk00v/DCC6N5nz59KvyaPXr0iOaVca+sW7cumseWff3+97+Pnt20aVOF5wCoLTp27BjNJ02aFM1btGgRze+7775M9tJLL+38YP/n2muvjeaDBw8u13VGjhxZ4Vl2JZ4cAwAAkDzlGAAAgOQpxwAAACRPOQYAACB5yjEAAADJs636XzRu3DiaH3744dH8lltuyWSnnHJKuV6zTp3szycKbfctZPny5dH84osvzmTbt28v17UBarvYxtEpU6ZEzx5wwAFVPU6VePnll6P5mDFjqnkSqLi999477xGopXbbLV6NBg4cmMl+/vOfR8/G3tuHUPj9fbdu3TLZDTfcED17zz33RPPmzZtnsv79+0fPlpSURPNHH300mj/00EPRvLby5BgAAIDkKccAAAAkTzkGAAAgecoxAAAAyVOOAQAASF6t31Zdr169THbkkUdGz06cODGat27dOppv2rQpkxXaHD1jxoxoftJJJ2WyQluzCym0We+ss87KZKNGjYqe3bp1a7leE6A2K7TNs1BeGcq74bQ8TjvttGh+8sknZ7Knn366wq8HValfv355j0Atdd5550Xzhx9+OJOVlZVFzxb6M/vtt9+O5sccc0xRWQghnHHGGdH8c5/7XCYr1F9WrlwZzb/+9a9H89R4cgwAAEDylGMAAACSpxwDAACQPOUYAACA5NWahVz169eP5rGFV7/73e/Kde0f/OAH0fzFF1/MZH/84x+jZ5s3b170NTp27FiO6UJo2bJlNL/99tsz2TvvvBM9+8QTT0TzLVu2lGsW+P9VxpKhnj17RvPRo0fv1Ezwr+bOnZvJevfuHT07cODAaP7MM89E882bN+/0XJ/lkksuieZDhgypkteDqjR16tRoXmiRHFTUgAEDovnYsWOj+bZt2zLZ2rVro2e/9rWvRfM1a9ZE87vvvjuT9erVK3q20KKu2LLIQgvDWrRoEc3ffffdaB77frho0aLo2drAk2MAAACSpxwDAACQPOUYAACA5CnHAAAAJE85BgAAIHklZYVWmf3/ByNb0PJQr169aD58+PBoft111xV97aeffjqaX3jhhdE8tqWu0Obo3//+99H8qKOOymRbt26Nnv3Rj34UzQtttz7jjDOieczzzz8fze+8885MVmjbXiGvv/56uc7HFPllWq1qyj1R023fvj2aV8bvaadOnaL5vHnzKnztms49kbZmzZpF89WrV5frOqeffnomK/S9sKZzT+y6zj777Gj+29/+Nppv2rQpkx1++OHRs0uWLNn5wXZx7onCYp8WE0IIBx54YDT/4Q9/mMkKbbYur9jX7kMPPRQ9261bt2henm3Vhfz617+O5oMGDSrXdWqyYv6beHIMAABA8pRjAAAAkqccAwAAkDzlGAAAgOQpxwAAACRvt7wH+Cx169bNZCNGjIievfbaa6P5xo0bM9n3vve96Nnx48dH89hW6hBCOOaYYzLZ6NGjo2ePPPLIaL5w4cJM9s1vfjN6durUqdG8adOm0bx79+6Z7IILLoie7devXzR/7rnnonnMu+++G83btm1b9DWofR588MFofsUVV1T42pdffnk0v+aaayp8bajJTjzxxLxHgErzySeflOt8bDNvgwYNKmscEjB58uRo/rvf/S6aF3qPWxlatGiRyQp9Ek0h559/fiabO3duua6xdOnScp2vrTw5BgAAIHnKMQAAAMlTjgEAAEiecgwAAEDylGMAAACSV6O3Vcc20RbaSv3xxx9H89hG3GeffTZ69rjjjovmF198cTQ/+eSTM1mjRo2iZ4cPHx7Nx44dm8nKuxFv3bp10fwPf/hDUVkI8S13IYTwta99reg5vv3tbxd9lnTMnz8/7xFITL169aJ53759o/mLL76YyTZt2lSpM1VE7HvQqFGjcpgEqkahzcGFvn8ceuihmazQpxRceeWVOz0XtVcef4Y2a9Ysmvfv3z+TFfokmkWLFkXzxx9/fOcHYweeHAMAAJA85RgAAIDkKccAAAAkTzkGAAAgeSVlZWVlRR0sKanqWTJWrFiRyVq2bBk9u2XLlmgeW+bQpEmT6Nl27dqVY7q4W2+9NZrffvvt0Xz79u0Vfs0UFPllWq3yuCdqkwULFkTzgw46qOhr1KkT//leoXu50CKLXZF74h969OiRyb7//e9Hz55wwgnRvG3btpmsvIsRy6N58+bR/JRTTonm9913XybbY489yvWahRaM9evXL5NNnTq1XNeuKdwTtc9PfvKTaB5bUrfvvvtGz27evLkyR9qluCdqlhtuuCGajxgxIpOtXLkyerZr167RfOnSpTs/WEKKuSc8OQYAACB5yjEAAADJU44BAABInnIMAABA8pRjAAAAkrdb3gN8lvfeey+TFdpW3aBBg2jeuXPnol/v97//fTSfPn16NH/iiScy2eLFi6NnbaWGHb355pvR/Atf+ELR1ygtLa2scdhFjR49OpN17NixXNf47ne/m8nWr1+/0zP9O4W2Zh911FHRvDwbZ6dNmxbNH3jggWi+q26mJm2xe2Lr1q05TAJZBx54YDS/9NJLo3ns63nMmDHRs7ZSVz1PjgEAAEiecgwAAEDylGMAAACSpxwDAACQPOUYAACA5NXobdU9e/bMZGeeeWb0bKEtnx988EEm+8UvfhE9u2bNmmhuAyJUvkKbGE8//fRqnoTUffOb38x7hM8U+z725JNPRs9effXV0Xzz5s2VOhPkqWnTppnsjDPOiJ6dNGlSVY8DO3juueeieaEt1o899lgmu+WWWyp1JornyTEAAADJU44BAABInnIMAABA8pRjAAAAkldSVlZWVtTBkpKqngUKKvLLtFq5Jyqm0GKKp556KpMddthh0bOFfg/at28fzRctWlTkdDWfe+IfunTpksmGDBkSPXvRRRdV8TRZsa+5jz/+OHr25Zdfjuax5XVz586t2GC1kHui9lm+fHk032uvvTLZkUceGT07f/78Sp1pV+KeyMcNN9wQzUeMGBHN+/fvn8kskqsaxdwTnhwDAACQPOUYAACA5CnHAAAAJE85BgAAIHnKMQAAAMmzrZpdgo2LsCP3RGENGjSI5oMHD47mP/zhDzNZbBtuCCE88cQT0fy5556L5pMnT85k7733XvQsFeOeqH3Gjx8fzWOfYNCvX7/o2SVLllTqTLsS9wTsyLZqAAAAKIJyDAAAQPKUYwAAAJKnHAMAAJA85RgAAIDk2VbNLsHGRdiRewJ25J6AHbknYEe2VQMAAEARlGMAAACSpxwDAACQPOUYAACA5CnHAAAAJE85BgAAIHnKMQAAAMlTjgEAAEiecgwAAEDylGMAAACSpxwDAACQPOUYAACA5CnHAAAAJE85BgAAIHnKMQAAAMlTjgEAAEheSVlZWVneQwAAAECePDkGAAAgecoxAAAAyVOOAQAASJ5yDAAAQPKUYwAAAJKnHAMAAJA85RgAAIDkKccAAAAkTzkGAAAgef8PLQvMXXo1zU8AAAAASUVORK5CYII=",
      "text/plain": [
       "<Figure size 1000x1000 with 10 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "# %%\n",
    "# 设置MNIST路径\n",
    "mnist_dir = '/media/jack/_cache1/24_CuiQiang/mnist'\n",
    "\n",
    "# 加载数据 (不展平以便可视化)\n",
    "(x_train, t_train), (x_test, t_test) = load_mnist(\n",
    "    mnist_dir=mnist_dir,\n",
    "    flatten=False,\n",
    "    normalize=False\n",
    ")\n",
    "\n",
    "# 显示第一张训练图像\n",
    "print(\"训练图像形状:\", x_train.shape)\n",
    "print(\"对应标签:\", t_train[0])\n",
    "img_show(x_train[0], reshape=False)\n",
    "\n",
    "# 显示前25张图像\n",
    "plt.figure(figsize=(10,10))\n",
    "for i in range(10):\n",
    "    plt.subplot(5,5,i+1)\n",
    "    plt.imshow(x_train[i], cmap='gray')\n",
    "    plt.title(str(t_train[i]))\n",
    "    plt.axis('off')\n",
    "plt.tight_layout()\n",
    "plt.show()\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "9a1f9c2e",
   "metadata": {},
   "outputs": [],
   "source": [
    "# "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "4836cf41",
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "bba52984",
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "80ec81c7",
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "ecf01457",
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "eab214e9",
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "40e77ee0",
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "markdown",
   "id": "828f0227",
   "metadata": {},
   "source": [
    "> **sys.path.append(os.pardir)**\n",
    " - python本身不支持跨目录调用文件\n",
    "- 该语句的目的是为了将父目录加入到sys.path (python的搜索模块的路径)\n",
    "- 使得python可以导入父目录下的任何目录中的任何文件"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "cq_jupyter",
   "language": "python",
   "name": "cq_jupyter"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 5
}
